#include <iostream>
#include <string>
#include <cerrno>  // errno.h
#include <cstring> // string.h
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

// fork之后子进程是能拿到父进程的数据的 --- 通信吗？写时拷贝，对方都看不到
// char buffer[1024]; // 不行的

const int size = 1024;


// 子进程进行读取
void SubProcessRead(int rfd)
{

    char inbuffer[size]; // c99 , gnu g99
    while (true)
    {
        sleep(2);
        std::cout << "子进程正在进行读取中：" << std::endl;

        ssize_t n = read(rfd, inbuffer, sizeof(inbuffer) - 1); // sizeof(inbuffer)->strlen(inbuffer);

        if (n > 0)
        {
            inbuffer[n] = 0;
            std:: cout << inbuffer << std::endl;
        }
        
    }
}

// 父进程进行写入
void FatherProcessWrite(int wfd)
{
    int cnt = 3;
    std::string message = "son, I am your father!!!";

    while (cnt --)
    {

        std::string info = message; // 这条消息，就是我们子进程发给父进程的消息
        write(wfd, info.c_str(), info.size());          // 写入管道的时候，没有写入\0, 有没有必要？没有必要

        std::cerr << info << std::endl;
    }

    std::cout << "father quit ..." << std::endl;
}

int main()
{
    // 1. 创建管道
    int pipefd[2];
    int n = pipe(pipefd); // 输出型参数，rfd， wfd

    // 返回 0 表示创建管道成功
    if (n != 0)
    {
        std::cerr << "errno: " << errno << ": "
                  << "errstring : " << strerror(errno) << std::endl;
        return 1;
    }

    sleep(1);

    // 2. 创建子进程
    pid_t id = fork();
    if (id == 0)
    {
        std::cout << "子进程关闭不需要的fd了, 准备发消息了" << std::endl;
        sleep(1);
        // 子进程 --- read
        // 3. 关闭不需要的fd
        close(pipefd[1]);

        SubProcessRead(pipefd[0]);

        close(pipefd[0]);
        exit(0);
    }

    std::cout << "父进程关闭不需要的fd了, 准备收消息了" << std::endl;
    sleep(1);
    // 父进程 --- write
    // 3. 关闭不需要的fd
    close(pipefd[0]);
    FatherProcessWrite(pipefd[1]);
    std::cout << "5s, father close rfd" << std::endl;
    sleep(5);
    close(pipefd[1]);

    int status = 0;
    pid_t rid = waitpid(id, &status, 0);
    if (rid > 0)
    {
        std::cout << "wait child process done, exit sig: " << (status & 0x7f) << std::endl;
        std::cout << "wait child process done, exit code(ign): " << ((status >> 8) & 0xFF) << std::endl;
    }
    return 0;
}